package com.firegod.live.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.firegod.commonutils.result.ResultCode;
import com.firegod.live.vo.LiveUser;
import com.firegod.servicebase.dao.CourseRepository;
import com.firegod.servicebase.dao.StudentRepository;
import com.firegod.servicebase.dao.TeacherRepository;
import com.firegod.servicebase.entity.Course;
import com.firegod.servicebase.exceptionhandler.exception.GuliException;
import com.firegod.shiro.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class LiveService {

    private static final LiveUser nullLiveUser = new LiveUser(null, null);
    @Autowired
    private TokenService tokenService;
    @Autowired
    private StudentRepository studentRepository;
    @Autowired
    private TeacherRepository teacherRepository;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private CourseRepository courseRepository;

    public synchronized HashMap<String, Object> join(String courseId) {
        String userIdWithType = tokenService.getCurrentUser();
        boolean isStudent = userIdWithType.substring(0, 7).equalsIgnoreCase("student");
        String userId = userIdWithType.substring(9);
        LiveUser liveUser;
        Set<LiveUser> liveUserSet;
        String userListString;
        String liveId = stringRedisTemplate.opsForValue().get("Live: " + userIdWithType);
        if (liveId != null && !courseId.equals(liveId)) {
            throw GuliException.from(ResultCode.IN_LIVE_ERROR);
        }
        userListString = stringRedisTemplate.opsForValue().get("Room: " + courseId);
        if (userListString != null) {
            List<LiveUser> liveUserList = JSONArray.parseArray(userListString, LiveUser.class);
            if (liveUserList != null) {
                if (isStudent) {
                    for (LiveUser liveUser1 : liveUserList) {
                        if (liveUser1.owner) {
                            if (stringRedisTemplate.opsForValue().get("Live: " + liveUser1.userId) == null) {
                                stringRedisTemplate.delete("Room: " + courseId);
                                Course course = courseRepository.getCourseByCourseId(courseId);
                                course.setLive(false);
                                courseRepository.saveAndFlush(course);
                                throw GuliException.from("直播已关闭！");
                            } else {
                                break;
                            }
                        }
                    }
                }
                liveUserList.remove(nullLiveUser);
                liveUserSet = new HashSet<>(liveUserList);
            } else {
                liveUserSet = new HashSet<>();
            }
        } else {
            throw GuliException.from("直播未开启！");
        }
        if (isStudent) {
            liveUser = new LiveUser(studentRepository.getByUserId(userId).getName(), userIdWithType, courseId, false);
        } else {
            liveUser = new LiveUser(teacherRepository.getByUserId(userId).getName(), userIdWithType, courseId, true);
        }
        stringRedisTemplate.opsForValue().set("Live: " + userIdWithType, courseId, 1, TimeUnit.MINUTES);
        HashMap<String, Object> map = new HashMap<>();
        liveUserSet.remove(liveUser);
        map.put("userList", liveUserSet.stream().map(LiveUser::toJSONObject).toArray(JSONObject[]::new));
        liveUserSet.add(liveUser);
        stringRedisTemplate.opsForValue().set("Room: " + courseId, Arrays.toString(liveUserSet.stream().map(LiveUser::toJSONObject).toArray(JSONObject[]::new)));
        map.put("self", liveUser.toJSONObject());
        return map;
    }

    public synchronized void inLive(String courseId) {
        String userIdWithType = tokenService.getCurrentUser();
        boolean isStudent = userIdWithType.substring(0, 7).equalsIgnoreCase("student");
//        String userId = userIdWithType.substring(9);
        String userListString = stringRedisTemplate.opsForValue().get("Room: " + courseId);
        List<LiveUser> liveUserList = JSONArray.parseArray(userListString, LiveUser.class);
        liveUserList.remove(nullLiveUser);
        if (isStudent) {
            for (LiveUser liveUser : liveUserList) {
                if (liveUser.owner) {
                    if (stringRedisTemplate.opsForValue().get("Live: " + liveUser.userId) == null) {
                        stringRedisTemplate.delete("Room: " + courseId);
                        Course course = courseRepository.getCourseByCourseId(courseId);
                        course.setLive(false);
                        courseRepository.saveAndFlush(course);
                        throw GuliException.from("直播已关闭！");
                    } else {
                        break;
                    }
                }
            }
        }
        stringRedisTemplate.opsForValue().set("Live: " + userIdWithType, courseId, 1, TimeUnit.MINUTES);
    }

    public void createLive(String courseId) {
        String userIdWithType = tokenService.getCurrentUser();
        boolean isStudent = userIdWithType.substring(0, 7).equalsIgnoreCase("student");
        String userId = userIdWithType.substring(9);
        LiveUser liveUser;
        String userListString = "[]";
        Set<LiveUser> liveUserSet = new HashSet<>();
        if (isStudent) {
            liveUser = new LiveUser(studentRepository.getByUserId(userId).getName(), userIdWithType, courseId, false);
        } else {
            liveUser = new LiveUser(teacherRepository.getByUserId(userId).getName(), userIdWithType, courseId, true);
        }
        stringRedisTemplate.opsForValue().set("Live: " + userIdWithType, courseId, 1, TimeUnit.MINUTES);
        liveUserSet.add(liveUser);
        HashMap<String, Object> map = new HashMap<>();
        map.put("userList", userListString);
        String jsonString = Arrays.toString(liveUserSet.stream().map(LiveUser::toJSONObject).toArray(JSONObject[]::new));
        stringRedisTemplate.opsForValue().set("Room: " + courseId, jsonString);
        Course course = courseRepository.getCourseByCourseId(courseId);
        course.setLive(true);
        courseRepository.saveAndFlush(course);
    }

    public synchronized void leave(String userIdWithType, String courseId) {
        String roomIdBackUp = stringRedisTemplate.opsForValue().get("Live: " + userIdWithType);
        if (roomIdBackUp == null || !roomIdBackUp.substring(6).equals(courseId)) {
            System.err.println("roomId与缓存不符！");
            return;
        }
        LiveUser liveUser = new LiveUser(userIdWithType, courseId);
        Set<LiveUser> liveUserSet;
        String userListString = stringRedisTemplate.opsForValue().get("Room: " + courseId);
        if (userListString == null) {
            throw GuliException.from("房间不存在！");
        }
        List<LiveUser> liveUserList = JSONArray.parseArray(userListString, LiveUser.class);
        if (liveUserList != null) {
            liveUserList.remove(nullLiveUser);
            liveUserSet = new HashSet<>(liveUserList);
        } else {
            liveUserSet = new HashSet<>();
        }
        liveUserSet.remove(liveUser);
        if (liveUserSet.isEmpty()) {
            stringRedisTemplate.delete("Room: " + courseId);
            Course course = courseRepository.getCourseByCourseId(courseId);
            course.setLive(false);
            courseRepository.saveAndFlush(course);
        } else {
            stringRedisTemplate.opsForValue().set("Room: " + courseId, Arrays.toString(liveUserSet.stream().map(LiveUser::toJSONObject).toArray(JSONObject[]::new)));
        }
        stringRedisTemplate.delete("Live: " + userIdWithType);
    }
}
